#include <stdlib.h>
#include <wiiuse/wpad.h>
#include <fat.h>

#include "Player.h"

#include "mario_png.h"
#include "colmap_png.h"
#include "tile_map.h"

extern void Debug(const char *msg);

using namespace std;


const int TILE_SIZE = 32;
const int GROUND = 300 - TILE_SIZE;
const int GRAVITY = 68;
const int SPEED = 512;

const int TileMap1Width = 16;
const int TileMap1Height = 16;
const int Map1Width = 512;
const int Map1Height = 30;


Player::Player(int lvl_len) {
	texPlayer = GRRLIB_LoadTexture(mario_png);
	texPlayerFlip = GRRLIB_CreateEmptyTexture(texPlayer->w, texPlayer->h);
	texColMap = GRRLIB_LoadTexture(colmap_png);
	
	GRRLIB_BMFX_FlipH(texPlayer, texPlayerFlip);
	GRRLIB_FlushTex(texPlayerFlip);
	GRRLIB_InitTileSet(texPlayer, TILE_SIZE, TILE_SIZE, 0);
	GRRLIB_InitTileSet(texPlayerFlip, TILE_SIZE, TILE_SIZE, 0);
	
	GRRLIB_InitTileSet(texColMap, TileMap1Width, TileMap1Height, 0);
	
	
	x = norm_fix(40); 
	y = norm_fix(GROUND-10); // bottom of the screen... fixed point
	
	vy = 0; // not jumping
	scrollx = 0;
	
	flipped = false;
	anim_cnt = 0;
	animation = 0;
	
	Life = 1;
	
	LevelLength = lvl_len;
	
	hitbox.leftup.x = 8; hitbox.leftup.y = 1; 
	hitbox.rightup.x = 20; hitbox.rightup.y = 1; 
	hitbox.leftdown.x = 8; hitbox.leftdown.y = 31; 
	hitbox.rightdown.x = 20; hitbox.rightdown.y = 31;
}

Player::~Player() {
	GRRLIB_FreeTexture(texPlayer);
	GRRLIB_FreeTexture(texPlayerFlip);
	GRRLIB_FreeTexture(texColMap);
}

s32 Player::GetX() {
	return x;
}

s32 Player::GetY() {
	return y;
}

s32 Player::GetScroll() {
	return scrollx;
}

void Player::SetScroll(s32 val) {
	scrollx = val;
}
	
void Player::Move() {
	// Move left or right
	if((WPAD_ButtonsHeld(0) & WPAD_BUTTON_UP) && (fix_norm(x) > 0)) {
		if(flipped == false) {
			flipped = true;
		}
		
		x -= 1 * SPEED;
		anim_cnt++;
	} else if(WPAD_ButtonsHeld(0) & WPAD_BUTTON_DOWN && (fix_norm(x) < LevelLength-TILE_SIZE*2)) {
		if(flipped) {
			flipped = false;
		}
		
		x += 1 * SPEED;
		anim_cnt++;
	}
	
	CheckCollisions();
	
	AnimateWalking();
}
	
void Player::Draw() {
	if(flipped)
		GRRLIB_DrawTile(fix_norm(x-scrollx), fix_norm(y), texPlayerFlip, 0, 1, 1, GRRLIB_WHITE, animation);
	else
		GRRLIB_DrawTile(fix_norm(x-scrollx), fix_norm(y), texPlayer, 0, 1, 1, GRRLIB_WHITE, animation);
}

bool Player::TouchingGround() {
	int leftx = (fix_norm(x)+hitbox.leftdown.x)/TileMap1Width+1;
	int lefty = (fix_norm(y)+hitbox.leftdown.y)/TileMap1Height;
	int rightx = (fix_norm(x)+hitbox.rightdown.x)/TileMap1Width+1;
	int righty = (fix_norm(y)+hitbox.rightdown.y)/TileMap1Height;
	
	int left = GetMapInfo(lefty, leftx);
	int right = GetMapInfo(righty, rightx);
	
	if(flipped && ((left != 0  && left != COLMAP_COIN) || (right != 0  && right != COLMAP_COIN)) && vy >= 0)
		return true;
	else if(((left != 0 && left != COLMAP_COIN) || (right != 0 && right != COLMAP_COIN)) && vy >= 0)
		return true;
	
	return false;
}

void Player::CheckCollisions() {
	int leftx = (fix_norm(x)+hitbox.leftdown.x)/TileMap1Width+1;
	int lefty = (fix_norm(y)+hitbox.leftdown.y-1)/TileMap1Height;
	int rightx = (fix_norm(x)+hitbox.rightdown.x)/TileMap1Width+1;
	int righty = (fix_norm(y)+hitbox.rightdown.y-1)/TileMap1Height;
	
	int rightup = GetMapInfo((fix_norm(y)+hitbox.rightup.y-1)/TileMap1Height, (fix_norm(x)+hitbox.rightup.x-2)/TileMap1Width+1);
	int rightdown = GetMapInfo((fix_norm(y)+hitbox.rightdown.y-1)/TileMap1Height, (fix_norm(x)+hitbox.rightdown.x-2)/TileMap1Width+1);
	int leftup = GetMapInfo((fix_norm(y)+hitbox.leftup.y+1)/TileMap1Height, (fix_norm(x)+hitbox.leftup.x+2)/TileMap1Width+1);
	int leftdown = GetMapInfo((fix_norm(y)+hitbox.leftdown.y-1)/TileMap1Height, (fix_norm(x)+hitbox.leftdown.x+2)/TileMap1Width+1);
	
	// Collision on the left of the sprite...
	if(GetMapInfo(lefty, leftx) == COLMAP_SOLID){
		x += norm_fix(2); // Move by 1 pixel...
	}
	
	// Collision on the right of the sprite...
	if(GetMapInfo(righty, rightx) == COLMAP_SOLID){
		x -= norm_fix(2); // Move by 1 pixel...
	}
	
	// Collision with the something on top
	if(vy <= 0 && (rightup == COLMAP_SOLID || leftup == COLMAP_SOLID)) {
	   y += norm_fix(1);
	   vy = 0;
	}
	
	// Collision on the bottom of the sprite...
	if(vy >= -1 && ((rightdown != 0 && rightdown != COLMAP_COIN && rightdown != COLMAP_FIN) || (leftdown != 0 && leftdown != COLMAP_COIN && leftdown != COLMAP_FIN))) {
		vy = 0;
		y -= norm_fix(2); // Move by 1/2 pixel...
	}
}

void Player::AnimateWalking() {
	if(animation != 2 && anim_cnt > 6) {
		animation ^= 1;
		anim_cnt = 0;
	}
	
	// If pressed 2 and not in the air - jump
	if ((WPAD_ButtonsDown(0) & WPAD_BUTTON_2) && TouchingGround()) {
		vy = -1870; // Start jumping
		jumping = true;
	}
	
	// Add gravity
	if(!TouchingGround()){
		vy += GRAVITY;
		
		if(vy > 2200) vy = 2200;
	}		
	y += vy;
	
	
	if(TouchingGround()) {
		vy = 0;
		jumping = false;
		
		if(animation == 2)
			animation = 0;
	}
	
	if(!TouchingGround()) 
		animation = 2;
	else if(!(WPAD_ButtonsHeld(0) & WPAD_BUTTON_DOWN || WPAD_ButtonsHeld(0) & WPAD_BUTTON_UP))
		animation = 0;
}
